#include "ULUI_LookupSingle.h"
#include "ULUI_PredictPickLucky.h"
#include "ULGfx_History.h"
#include "ULGfx_CrossHair.h"
#include "ULGfx_Bomb.h"
#include "ULGfx_CrossHair.h"
#include "ULCore_Prediction.h"
#include "ULCore_Algorithm.h"
#include "UL_Global.h"
#include "UL_Tools.h"
#include "VSDL_tools.h"

#define PREDICT_PICK_LUCKY_START_X	100
#define PREDICT_PICK_LUCKY_START_Y	100

static ULC_Serial predictedSerial;
static ULC_ACData acData;
static int lastAC;
bool reset = false;
bool done = false;
int bombsXYSet;
bool blueSelected;
int redSelected;
int reds[6];
int blue;
int redNumbers[UL_BALL_MAX_RED];
int blueNumbers[UL_BALL_MAX_BLUE];
ULG_Bomb redBombs[UL_BALL_MAX_RED]; //33 reds and 16 blue
ULG_Bomb blueBombs[UL_BALL_MAX_BLUE];
ULG_CrossHair cross;

ULUI_PredictPickLucky ULUI_PredictPickLucky::predictPickLucky;

enum BinLookupIDs{
	RESET,
	EXIT,	
};	

static char *menuTitles[] = {
	"重新选择",
	"返回"
};

static bool NumberExisted(int *numbers, int index, int number)
{
	for (int i = 0; i <= index; i++){
		if (numbers[i] == number){
			return true;
		}
	}

	return false;
}

static void InitNumbers()
{
	int i;
	int number;

	memset(redNumbers, 0 , sizeof(int) * UL_BALL_MAX_RED);
	memset(blueNumbers, 0 , sizeof(int) * UL_BALL_MAX_BLUE);
	memset(reds, 0, sizeof(int) * UL_RED_BALLS_COUNT);
	blue = 0;

	for (i = 0; i < UL_BALL_MAX_RED; i++){
		number = VSDL_Tool::Rand() % UL_BALL_MAX_RED + 1;

		if (i > 0){
			while (NumberExisted(redNumbers, i - 1, number)){
				number = VSDL_Tool::Rand() % UL_BALL_MAX_RED + 1;
			}
		}

		redNumbers[i] = number;
	}

	for (i = 0; i < UL_BALL_MAX_BLUE; i++){
		number = VSDL_Tool::Rand() % UL_BALL_MAX_BLUE + 1;

		if (i > 0){
			while (NumberExisted(blueNumbers, i - 1, number)){
				number = VSDL_Tool::Rand() % UL_BALL_MAX_BLUE + 1;
			}
		}

		blueNumbers[i] = number;
	}

	//Debug
	cout << "RedNumbers: ";
	for (i = 0; i < UL_BALL_MAX_RED; i++){
		cout << redNumbers[i] << "  ";
	}

	cout << endl << "BlueNumbers:";
	for (i = 0; i < UL_BALL_MAX_BLUE; i++){
		cout << blueNumbers[i] << "  ";
	}
	cout << endl;


	ULG_History *ulgHistory = ULG_History::Instance();
	acData.Caculate(&ulgHistory->GetLatestSerial()->sortedBalls);
	lastAC = acData.ac;

}

static void InitBombs()
{	
	int i;
	//Init red bombs
	for (i = 0; i < UL_BALL_MAX_RED; i++){
		redBombs[i].Init();
	}
	//Init blue bombs
	for (i = 0; i < UL_BALL_MAX_BLUE; i++){
		blueBombs[i].Init();
	}
}

static void Reset()
{
	int i;

	blueSelected = false;
	redSelected = 0;
	bombsXYSet = 0;
	done = false;

	InitBombs();
	InitNumbers();
}

static void ShowBombs(SDL_Surface *destSurf, bool red, VSDL_Point &currentXY)
{
#define BOMBS_PER_ROW	7	
	int i;
	int count = 0;
	int size;
	ULG_Bomb *bombs;
	int startX = currentXY.x;
	int bombWidth, bombHeight;

	if (red){
		bombs = redBombs;
		size = UL_BALL_MAX_RED;
	}else{
		bombs = blueBombs;
		size = UL_BALL_MAX_BLUE;
	}

	bombWidth = bombs[0].GetWidth();
	bombHeight = bombs[0].GetHeight();
	bombWidth >>= 1;

	if (bombsXYSet >= (UL_BALL_MAX_RED + UL_BALL_MAX_BLUE)){
		for (i = 0; i < size; i++){
			bombs[i].Show(destSurf);
			count++;

			if (count == BOMBS_PER_ROW){
				currentXY.y += bombHeight;
				count = 0;
			}
		}
	}else{
		for (i = 0; i < size; i++){
			currentXY.x += bombWidth;
			bombs[i].SetStartXY(currentXY);
			bombs[i].Show(destSurf);
			count++;

			if (count == BOMBS_PER_ROW){
				currentXY.x = startX;
				currentXY.y += bombHeight;
				count = 0;
			}
		}
		
		bombsXYSet += size;
	}

	currentXY.y += bombHeight;
	currentXY.x = startX;
}

void ULUI_PredictPickLucky::Init()
{
	int i;
	VSDL_Point currentXY(PREDICT_PICK_LUCKY_START_X, PREDICT_PICK_LUCKY_START_Y);
	int w, h;
	ULUI_Menu menu;
	int ret;
	ULG_History *ulgHistory = ULG_History::Instance();

	AttachEventHandler(this);


	SDL_ShowCursor(0);
	menu.SetFont(UL_Global::UnionLottoFont());
	menu.ShowBoarder(true);
	selectedMenu = -1;

	for (i = 0; i <= EXIT; i++){
		menu.SetID(i);
		menu.SetTitle(menuTitles[i]);
		menus.AddMenu(menu);
	}

	menus.SetFirstMenuXY(VSDL_Point(PREDICT_PICK_LUCKY_START_X, PREDICT_PICK_LUCKY_START_Y));
	menu.GetTitleSize(w, h);
	Reset();
	cross.Init();
}

void ULUI_PredictPickLucky::CleanUp()
{
	menus.Reset();
	SDL_ShowCursor(1);
}

void ULUI_PredictPickLucky::Pause()
{
}

void ULUI_PredictPickLucky::Resume()
{
	selectedMenu = -1;
}

void ULUI_PredictPickLucky::Update(VSDL_GameEngine *game)
{
	if (done == false){
		if (redSelected == 6 && blueSelected){
			done = true;
			predictedSerial.actualOutBalls.SetNumbers(reds, blue);
			predictedSerial.sortedBalls.SetNumbers(reds, blue);
			predictedSerial.sortedBalls.SortRedBalls();

		}
	}

	if (selectedMenu == -1){
		return ;
	}

	switch (selectedMenu){
		case RESET:
			Reset();
			selectedMenu = -1;
			break;
		case EXIT:
			game->PopState();
			break;
	}
}

void ULUI_PredictPickLucky::Draw(VSDL_GameEngine *game)
{
	VSDL_RGB rgb(100, 100, 100);
	VSDL_Point currentXY(PREDICT_PICK_LUCKY_START_X, PREDICT_PICK_LUCKY_START_Y);
	int fontHeight;
	char msgBuffer[256];
	ULG_Serial *ulgSerial = UL_Global::UnionLottoSerial();
	SDL_Surface *destSurf = game->GetSurface();

	UL_Global::UnionLottoShowBg();
	UL_Global::UnionLottoShowTitle();
	menus.Show(destSurf);

	fontHeight = UL_Global::UnionLottoGetFontHeight();
	currentXY.y += fontHeight * (EXIT + 1);
	//Draw result rect
	SPG_RectFilled(destSurf, currentXY.x, currentXY.y, destSurf->w, destSurf->h, rgb.GetRGB32(destSurf));

	if (done == false){
		UL_Global::UnionLottoShowTip("红球区:", currentXY);
		currentXY.y += fontHeight;
		ShowBombs(destSurf, true, currentXY);
		currentXY.y += fontHeight;
		UL_Global::UnionLottoShowTip("蓝球区:", currentXY);
		currentXY.y += fontHeight;
		ShowBombs(destSurf, false, currentXY);
		//Show picked numbers
		currentXY.y += fontHeight;
		sprintf(msgBuffer, "已选红球:%02d %02d %02d %02d %02d %02d", reds[0], reds[1], reds[2], reds[3], reds[4], reds[5]);
		UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
		currentXY.y += fontHeight;
		sprintf(msgBuffer, "已选蓝球:%02d", blue);
		UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
		cross.Show(destSurf);
		return ;
	}

	if (done){
		UL_Global::UnionLottoShowTip("预测结果(幸运选号):", currentXY);
		currentXY.y += fontHeight;
		*ulgSerial = predictedSerial;
		ulgSerial->SetXY(currentXY);
		ulgSerial->Show(destSurf);

		currentXY.x += (destSurf->w >> 1);

		char msgBuffer[128];
		sprintf(msgBuffer, "上期AC: %d", lastAC);
		UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
		currentXY.y += fontHeight;

		acData.Caculate(&predictedSerial.sortedBalls);
		sprintf(msgBuffer, "预测AC: %d", acData.ac);
		UL_Global::UnionLottoShowTip(msgBuffer, currentXY);
		currentXY.y += fontHeight;

		if (retList.size() == 0){
			UL_Global::UnionLottoShowTip("历史数据中没有与该预测重复的结果", currentXY);
		}else{
			ULC_Serial *ulcSerial;

			UL_Global::UnionLottoShowTip("历史数据中与该预测重复的结果有:", currentXY);
			currentXY.y += fontHeight;

			for (iter = retList.begin(); iter != retList.end(); iter++){
				ulcSerial = *iter;

				sprintf(msgBuffer, "期号:% 10d 日期:  %s", ulcSerial->sn, ulcSerial->date);
				UL_Global::UnionLottoShowTip(msgBuffer, currentXY);

				currentXY.y += fontHeight;
			}
		}
	}

	cross.Show(destSurf);
}

ULUI_PredictPickLucky *ULUI_PredictPickLucky::Instance()
{
	return &predictPickLucky;
}


void __HANDLE_EVENT ULUI_PredictPickLucky::OnKeyDown(SDLKey keysym, unsigned char *keyStates, void *arg)
{
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	if (keyStates[SDLK_ESCAPE]){
		game->PopState();
	}
}

void __HANDLE_EVENT ULUI_PredictPickLucky::OnMouseMove(int button, unsigned char buttonState, int absX, int absY, int relX, int relY, void *arg)
{
	int i;

	menus.UpdateMenuList(absX, absY);

	if (done == false){

		for (i = 0; i < UL_BALL_MAX_RED; i++){
			redBombs[i].OnMouseMove(absX, absY);
		}

		for (i = 0; i < UL_BALL_MAX_BLUE; i++){
			blueBombs[i].OnMouseMove(absX, absY);
		}

	}

	cross.OnMouseMove(absX, absY);
}

void __HANDLE_EVENT ULUI_PredictPickLucky::OnMouseDown(int button, unsigned char buttonState, int absX, int absY, void *arg)
{
	int i;
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	selectedMenu = -1;

	for (i = 0; i <= EXIT; i++){
		ULUI_Menu &menu = menus.GetMenu(i);

		if (menu.IsXYInRect(absX, absY)){
			selectedMenu = i;
			break;
		}
	}

	if (redSelected != 6){
		for (i = 0; i < UL_BALL_MAX_RED; i++){
			if (redBombs[i].OnMouseDown(absX, absY)){
				cout << "Picked red" << endl;
				reds[redSelected++] = redNumbers[i];
				break;
			}
		}
	}

	if (blueSelected == false){
		for (i = 0; i < UL_BALL_MAX_BLUE; i++){
			if (blueBombs[i].OnMouseDown(absX, absY)){
				blue = blueNumbers[i];
				blueSelected = true;
				break;
			}
		}
	}
}

void __HANDLE_EVENT ULUI_PredictPickLucky::OnQuit(void *arg)
{
	VSDL_GameEngine *game = reinterpret_cast<VSDL_GameEngine *>(arg);

	game->Quit();
}
